/*
 * StartApplication.java
 *
 * Created on Jul 21, 2009 4:48:43 PM;
 */

package org.sunspotworld;

import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.peripheral.radio.RadioFactory;
import com.sun.spot.io.j2me.radiogram.*;
import com.sun.spot.peripheral.TimeoutException;
import com.sun.spot.peripheral.radio.RadioPacket;
import com.sun.spot.resources.transducers.ISwitch;
import com.sun.spot.resources.transducers.ISwitchListener;
import com.sun.spot.resources.transducers.ITriColorLED;
import com.sun.spot.util.*;

import java.io.IOException;
import javax.microedition.io.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

/**
 * The startApp method of this class is called by the VM to start the
 * application.
 * 
 * The manifest specifies this class as MIDlet-1, which means it will
 * be selected for execution.
 */
public class StartApplication extends MIDlet implements ISwitchListener {
    private static final int PAYLOAD_SIZE = RadioPacket.MIN_PAYLOAD_LENGTH-5;

    private ITriColorLED [] leds = EDemoBoard.getInstance().getLEDs();
    private static final long SECONDS = 1000;
    private static final long PAUSE = 4*SECONDS;
    private RadiogramConnection cmdConn;
    private RadiogramConnection dataConn;
    private static final String CMD_PORT = "87";
    private static final String DATA_PORT = "89";

    private Queue readingQueue = new Queue();
    private boolean running = true;

    private Thread readingThread = new Thread() {
        public void run() {
            while (running) {
                readingQueue.put(new GPSReading());
                Utils.sleep(PAUSE);
            }
        }
    };

    protected void startApp() throws MIDletStateChangeException {
        System.out.println("Hello, world");
        new BootloaderListener().start();   // monitor the USB (if connected) and recognize commands from host

        long ourAddr = RadioFactory.getRadioPolicyManager().getIEEEAddress();
        System.out.println("Our radio address = " + IEEEAddress.toDottedHex(ourAddr));
        try {
            cmdConn = (RadiogramConnection) Connector.open("radiogram://:"+CMD_PORT);
            dataConn = (RadiogramConnection) Connector.open("radiogram://:"+DATA_PORT);
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        ISwitch sw1 = EDemoBoard.getInstance().getSwitches()[EDemoBoard.SW1];
        sw1.addISwitchListener(this);
        leds[0].setRGB(100,0,0);                // set color to moderate red
        leds[7].setRGB(0,0,100);                // set color to moderate red
        GPSReading.init();
        readingThread.start();
        
        Radiogram rrg; Radiogram xrg;
        int size;
        GPSReading reading;
        while (running) {
            try {
                rrg = (Radiogram)cmdConn.newDatagram(cmdConn.getMaximumLength());
                xrg = (Radiogram)dataConn.newDatagram(dataConn.getMaximumLength());
                while (running) {                  // done when switch is pressed
                    try {
                        rrg.reset();
                        cmdConn.receive(rrg);
                        leds[7].setOn();                    // Blink LED
                        System.out.println("Poll Received");
                        while (running && !readingQueue.isEmpty()) {
                            System.out.println("sending data...");
                            size = 0;
                            xrg.reset();
                            xrg.setAddress(rrg);
                            while (size < PAYLOAD_SIZE + GPSReading.SIZE && !readingQueue.isEmpty()) {
                                System.out.println("Packet size: " + size);
                                reading = (GPSReading)readingQueue.get();
                                xrg.writeInt(reading.getLightReading());
                                xrg.writeDouble(reading.getGpsReading()[0]);
                                xrg.writeDouble(reading.getGpsReading()[1]);
                                xrg.writeDouble(reading.getGpsReading()[2]);
                                xrg.writeLong(reading.getTime());
                                size += GPSReading.SIZE;
                            }
                            dataConn.send(xrg);
                            System.out.println("Data sent");
                        }
                        leds[7].setOff();                    // Blink LED
                    } catch (TimeoutException ex) {
                    }
                    leds[0].setOn();                    // Blink LED
                    Utils.sleep(PAUSE / 2);                  // wait 1 second
                    leds[0].setOff();
                    Utils.sleep(PAUSE / 2);
                }
            } catch (IOException iOException) {
            }
            if (cmdConn != null) {
                try {
                    cmdConn.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }

        }
        try {
            readingThread.join();
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        notifyDestroyed();                      // cause the MIDlet to exit
    }

    protected void pauseApp() {
        // This is not currently called by the Squawk VM
    }

    /**
     * Called if the MIDlet is terminated by the system.
     * I.e. if startApp throws any exception other than MIDletStateChangeException,
     * if the isolate running the MIDlet is killed with Isolate.exit(), or
     * if VM.stopVM() is called.
     * 
     * It is not called if MIDlet.notifyDestroyed() was called.
     *
     * @param unconditional If true when this method is called, the MIDlet must
     *    cleanup and release all resources. If false the MIDlet may throw
     *    MIDletStateChangeException  to indicate it does not want to be destroyed
     *    at this time.
     */
    protected void destroyApp(boolean unconditional) throws MIDletStateChangeException {
        for (int i = 0; i < 8; i++) {
            leds[i].setOff();
        }
    }

    public void switchPressed(ISwitch sw) {
        running = false;
    }

    public void switchReleased(ISwitch sw) {
    }


}
